#include "my_time.h"

#define FEBRUARY		    2
#define	STARTOFTIME		    1970
#define SECDAY			    86400L           /*  一天有多少s */
#define SECYR			    (SECDAY * 365)
#define	leapyear(year)		((year) % 4 == 0)
#define	days_in_year(a) 	(leapyear(a) ? 366 : 365)
#define	days_in_month(a) 	(month_days[(a) - 1])

static int month_days[12] = {	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

/*
 * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
 */
/*计算公历*/
void GregorianDay(struct rtc_time * tm)
{
    int leapsToDate;
    int lastYear;
    int day;
    int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };

    lastYear = tm->tm_year - 1;

    /*计算从公元元年到计数的前一年之中一共经历了多少个闰年*/
    leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400;

    /*如若计数的这一年为闰年，且计数的月份在2月之后，则日数加1，否则不加1*/
    if((tm->tm_year % 4 == 0) &&
            ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) &&
            (tm->tm_mon > 2))
    {
        /*
         * We are past Feb. 29 in a leap year
         */
        day = 1;
    }
    else
    {
        day = 0;
    }

    day += lastYear * 365 + leapsToDate + MonthOffset[tm->tm_mon - 1] + tm->tm_mday; /*计算从公元元年元旦到计数日期一共有多少天*/

    tm->tm_wday = day % 7;
}

/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
 *
 * [For the Julian calendar (which was used in Russia before 1917,
 * Britain & colonies before 1752, anywhere else before 1582,
 * and is still in use by some communities) leave out the
 * -year/100+year/400 terms, and add 10.]
 *
 * This algorithm was first published by Gauss (I think).
 *
 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
 * machines were long is 32-bit! (However, as time_t is signed, we
 * will already get problems at other places on 2038-01-19 03:14:08)
 *
 */
uint32_t mktimev(struct rtc_time *tm)
{
    if (0 >= (int) (tm->tm_mon -= 2))  	/* 1..12 -> 11,12,1..10 */
    {
        tm->tm_mon += 12;		/* Puts Feb last since it has leap day */
        tm->tm_year -= 1;
    }

    return (((
                 (uint32_t) (tm->tm_year / 4 - tm->tm_year / 100 + tm->tm_year / 400 + 367 * tm->tm_mon / 12 + tm->tm_mday) +
                 tm->tm_year * 365 - 719499
             ) * 24 + tm->tm_hour /* now have hours */
            ) * 60 + tm->tm_min /* now have minutes */
           ) * 60 + tm->tm_sec; /* finally seconds */
}

void to_tm(uint32_t tim, struct rtc_time * tm)
{
    register uint32_t    i;
    register long   hms, day;

    day = tim / SECDAY;			/* 有多少天 */
    hms = tim % SECDAY;			/* 今天的时间，单位s */

    /* Hours, minutes, seconds are easy */
    tm->tm_hour = hms / 3600;
    tm->tm_min = (hms % 3600) / 60;
    tm->tm_sec = (hms % 3600) % 60;

    /* Number of years in days */ /*算出当前年份，起始的计数年份为1970年*/
    for (i = STARTOFTIME; day >= days_in_year(i); i++)
    {
        day -= days_in_year(i);
    }

    tm->tm_year = i;

    /* Number of months in days left */ /*计算当前的月份*/
    if (leapyear(tm->tm_year))
    {
        days_in_month(FEBRUARY) = 29;
    }

    for (i = 1; day >= days_in_month(i); i++)
    {
        day -= days_in_month(i);
    }

    days_in_month(FEBRUARY) = 28;
    tm->tm_mon = i;

    /* Days are what is left over (+1) from all that. *//*计算当前日期*/
    tm->tm_mday = day + 1;

    /*
     * Determine the day of week
     */
    GregorianDay(tm);
}

